package hs.framework.opcClient.controller;

import hs.framework.opcClient.utils.ClockMessage;
import hs.framework.opcClient.service.impl.OPCService;
import hs.framework.opcClient.utils.JiVariantUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jinterop.dcom.common.JIException;
import org.openscada.opc.lib.da.Group;
import org.openscada.opc.lib.da.Item;
import org.openscada.opc.lib.da.ItemState;
import org.openscada.opc.lib.da.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.messaging.simp.annotation.SendToUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;

import java.security.Principal;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@CrossOrigin
@Controller
public class SocketController {
    private final static Log log = LogFactory.getLog(SocketController.class);

    private String test;

    private String itemMessage;

    @Autowired
    OPCService opcService;


    @Autowired
    private SimpMessagingTemplate template;

    private static final ScheduledThreadPoolExecutor executor =  new ScheduledThreadPoolExecutor(1);


    public static void stopThreadByName(String name){
        for (Thread t:Thread.getAllStackTraces().keySet()){
            if (t.getName().equals(name)){
                t.stop();
            }
        }

    }

    /**
     * SendTo SendToUser两个注解必须和 MessageMapping一起用在有作用；
     * SendToUser只是发给消息来源用户的订阅队列里； SendTo则发送到所有用户的订阅队列里
     *
     * 不写SendTo/SendToUser注解，只写MessageMapping注解，也能接收客户端发送过来的消息。
     * SendTo注解的作用是给客户端发消息（发送到订阅队列里，不是回接收的客户端的消息，STOMP中无回消息的概念）
     *
     * MessageMapping注解中配置的接收地址和WebScoketConfig中setApplicationDestinationPrefixes()设置的地址前缀
     * 一起构成了客户端向服务器端发送消息时使用地址
     */
    @MessageMapping("/all")
    @SendTo("/topic/clockmessage")
    public ClockMessage toAll(ClockMessage message, Principal principal) throws Exception {
        if(log.isTraceEnabled()) {
            log.trace("toAll(接受到消息)" + message);
        }
        Thread.sleep(100);
        //这个方法也能发
        this.template.convertAndSend("/topic/clockmessage",  new ClockMessage("Hello, from controller now!"));

        //由于使用注解@SendTo，返回结果也会被convertAndSend
        return new ClockMessage("toAll, 来自"  + principal.getName() + "的消息：" + message.getMessage() + " ");
    }

    @MessageMapping("/one")
    @SendToUser("/topic/clockmessage")
    public void toOne(ClockMessage message, Principal principal) throws Exception {
        itemMessage = message.getMessage();
        //由于增加了SendToUser注解，返回结果会被convertAndSend给特定用户，调用这个方法发消息的用户principal中的用户
        Server server = opcService.openServer();

        String result = "ItemID"+message.getMessage()+"测定值：";
        //stopThreadByName("UtgardSyncReader");

            Group group = server.addGroup(message.getMessage());
            Item item = group.addItem(message.getMessage());
            Runnable runnable = ()->{
                try {
                    ItemState itemState = item.read(false);
                    log.error("监控项的数据类型是：-----" + itemState.getValue().getType());
                    log.error("监控项的时间戳是：-----" + itemState.getTimestamp().getTime());
                    log.error("监控项的详细信息是：-----" + itemState.getValue());
                    log.error("监控项的点位名称是：------" + itemMessage);
                    // 类型实际是数字，用常量定义的
                    test = JiVariantUtil.parseVariant(itemState.getValue())+"";
                    log.error(result+"-----"+test);
                } catch (JIException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                if (itemMessage.equals(message.getMessage())){
                    template.convertAndSendToUser(principal.getName(),"/topic/clockmessage",new ClockMessage(test));
                }
            };
        executor.scheduleAtFixedRate(runnable,500,1000,TimeUnit.MILLISECONDS);

    }

}
